#include "settings.h"
#include "mlog.h"
#include <string.h>

/*参数结构体*/
SystemSettings SystemSetting[SETTINGS_MAX_NUM] = {0};
/*实际存储参数的地方*/
char SystemSettingsBuf[SETTINGS_BUF_SIZE] = {0};
/*临时缓存参数的地方*/
char SystemSettingsBufTemp[SETTINGS_BUF_SIZE] = {0};

settings_ini si = {0};


uint8_t System_SettingsSave(void)
{
	/*计算crc*/
	if(Modbus_CRC16(SystemSettingsBuf, SETTINGS_BUF_SIZE) != 0)
	{
		mprintf(LOG_ERROR, "param crc error:%d:%d.\r\n", SystemSettingsBuf[SETTINGS_BUF_SIZE - 1], SystemSettingsBuf[SETTINGS_BUF_SIZE - 2]);
		return SETTINGS_CRC_ERROR;
	}
	
	if(si.storage_write(si.start_addr, SystemSettingsBuf, SETTINGS_BUF_SIZE))
	{
		mprintf(LOG_ERROR, "write param error.\r\n");
		return SETTINGS_WRITE_ERROR;
	}

	return SETTINGS_OK;
}
/*
 * brief:恢复出厂设置
 */
uint8_t System_SettingsRestore(void)
{
	uint8_t ret = 0;
	uint32_t i = 0;
	uint32_t len = 0, total_len = 0, pos = 0;
	uint16_t crc = 0;
	
	if(si.default_settings == NULL)
	{
		mprintf(LOG_INFO, "si.default_settings is null.\r\n");
	}
	else
	{
		si.default_settings();
	}
	
	memset(SystemSettingsBuf, 0, SETTINGS_BUF_SIZE);
	
	for(i = 0;i < SETTINGS_MAX_NUM; i++)
	{
		len = SystemSetting[i].ptr ? strlen(SystemSetting[i].ptr) : 0;
		if(len > (SETTINGS_BUF_SIZE - total_len -1))
		{
			mprintf(LOG_ERROR, "param len error,len:%d, total_len:%d.\r\n", len, total_len);
			return SETTINGS_LEN_ERROR;
		}

		mprintf(LOG_INFO, "param %d len %d:%s.\r\n", i, len, len > 0 ? (char*)SystemSetting[i].ptr : "unkown.");
		if(SystemSetting[i].ptr)
		{
			strcpy(&SystemSettingsBuf[pos], (char*)SystemSetting[i].ptr);
		}
		/*每个参数都是字符串，字符串是以0x00结尾，没有参数的地方也要0x00占位*/
		pos = pos + len + 1;
	}
	mprintf(LOG_INFO, "param tottal len :%d.\r\n", pos);
	/*计算crc*/
	crc = Modbus_CRC16(SystemSettingsBuf, SETTINGS_BUF_SIZE - 2);
	if(pos > (SETTINGS_BUF_SIZE-2))
	{
		mprintf(LOG_ERROR,"param total length over limit:%d:%d.\r\n", SETTINGS_BUF_SIZE,len);
		return SETTINGS_LEN_ERROR;
	}
	mprintf(LOG_INFO, "234");
	/*最后两个字节保存crc*/
	SystemSettingsBuf[SETTINGS_BUF_SIZE-1] = (crc >> 8);
	SystemSettingsBuf[SETTINGS_BUF_SIZE-2] = crc;
	if(si.storage_write(si.start_addr, SystemSettingsBuf, SETTINGS_BUF_SIZE))
	{
		mprintf(LOG_ERROR,"write param error!\r\n");
		return SETTINGS_WRITE_ERROR;
	}
	return ret;
}

/*统计参数表长度，每个参数都是字符串，字符串是以0x00结尾*/
uint32_t System_SettingsTotalLength(void)
{
	uint32_t len = 0, total_len = 0, i = 0, j = 0;
	for(i = 0; i < SETTINGS_MAX_NUM; i++)
	{
		len = strlen(&SystemSettingsBuf[j]) + 1;
		if(len > (SETTINGS_BUF_SIZE - j - 1))
		{
			mprintf(LOG_ERROR, "param length error.\r\n");
			return 0;
		}
		else
		{
			/*字符串是以0x00结尾所以要多加一个1，没有参数的地方也要0x00占位*/
			total_len = total_len + len;
			/*字符串是以0x00结尾所以要多加一个1，没有参数的地方也要0x00占位*/
			j = j + len + 1;
		}
	}
	return total_len;
}
/*
 * 指针指向参数缓存的位置
 */
void System_SettingsAllign(void)
{
	uint32_t i = 0;
	uint32_t len = 0;
	uint32_t pos = 0;


	for(i = 0; i < SETTINGS_MAX_NUM; i++)
	{
		SystemSetting[i].ptr = &SystemSettingsBuf[pos];
		len = strlen(&SystemSettingsBuf[pos]);
		if(len > (SETTINGS_BUF_SIZE - pos - 1))
		{
			mprintf(LOG_ERROR, "param length error.\r\n");
			return;
		}
		else
		{
			/*字符串是以0x00结尾所以要多加一个1，没有参数的地方也要0x00占位*/
			pos = pos + len + 1;
			mprintf(LOG_INFO, "%s%03d,len:%03d:%s\r\n",SystemSetting[i].name ? SystemSetting[i].name : "UNKOWN:", i, strlen(SystemSetting[i].ptr), SystemSetting[i].ptr);
		}
	}
	mprintf(LOG_INFO, "param total len:%d.\r\n", pos);
}
void System_SettingsInit(void)
{
	if(si.default_settings == NULL)
	{
		mprintf(LOG_INFO, "si.default_settings is null.\r\n");
	}
	else
	{
		si.default_settings();
	}

	si.storage_read(si.start_addr, SystemSettingsBuf,SETTINGS_BUF_SIZE);

	if(memcmp(SystemSettingsBuf, SystemSetting[0].ptr, strlen(SystemSetting[0].ptr)))
	{
		mprintf(LOG_INFO, "init param frist.\r\n");
		System_SettingsRestore();
		System_SettingsAllign();
	}
	else
	{
		if(Modbus_CRC16(SystemSettingsBuf, SETTINGS_BUF_SIZE) != 0)
		{
			mprintf(LOG_INFO,"param crc error.\r\n");
			System_SettingsRestore();
		}
		System_SettingsAllign();
	}
}



void System_SettingsReport(void)
{
	uint32_t i = 0, len = 0, total_len = 0;
	for(i = 0; i < SETTINGS_MAX_NUM; i++)
	{
		/*统计参数表长度，每个参数都是字符串，字符串是以0x00结尾*/
		total_len = total_len + strlen(SystemSetting[i].ptr) + 1;
		mprintf(LOG_IMP, "%s%03d,len:%03d:%s\r\n", SystemSetting[i].name ? SystemSetting[i].name : "UNKOWN:",i, strlen(SystemSetting[i].ptr), SystemSetting[i].ptr);
	}
	mprintf(LOG_IMP, "param total len:%d.\r\n",len);
}

uint8_t is_print_char(uint8_t* data, uint16_t len)
{
	uint16_t i = 0;
	for(i = 0; i < len; i++)
	{
		if((data[i] < 32) || (data[i] >126))
		{
			return 0;
		}
	}
	return 1;
}
/*
 * data参数必须是字符串（字符串是以0x00结尾的数组）
 */
uint8_t System_SettingsSetSingle(uint16_t num, char* data , uint16_t len)
{
	uint32_t count = 0;
	uint32_t free_len = 0;
	uint16_t crc = 0;

	mprintf(LOG_INFO, "set param :%d:%s\r\n", num, data);
	
	if(!is_print_char(data, len))
	{
		mprintf(LOG_ERROR,"is not a valid string.\r\n");
		return SETTINGS_STRING_ERROR;
	}
	
	if(num >= SETTINGS_MAX_NUM)
	{
		mprintf(LOG_ERROR,"param num error:%d.\r\n",num);
		return SETTINGS_NUM_ERROR;
	}
	/*可用长度 = 该参数原来长度 + 存储总长度 - 已用总长度 - 2个字节crc*/
	free_len = strlen(SystemSetting[num].ptr) + SETTINGS_BUF_SIZE - System_SettingsTotalLength() - 2;
	if(strlen(data) > free_len)
	{
		mprintf(LOG_ERROR,"param len error:%d.\r\n", strlen(data));
		return SETTINGS_LEN_ERROR;
	}
	if(data == NULL)
	{
		mprintf(LOG_ERROR, "param err.\r\n");
		return SETTINGS_DATA_ERROR;
	}
	memset(SystemSettingsBufTemp, 0, SETTINGS_BUF_SIZE);
	/*1.先把该参数后面的参数缓存起来*/
	count = SETTINGS_BUF_SIZE - (SystemSetting[num + 1].ptr - SystemSettingsBuf);
	mprintf(LOG_INFO, "LEN:%d.\r\n", count);
	memcpy(SystemSettingsBufTemp, SystemSetting[num + 1].ptr, count);
	/*2.将要写入的参数写入,并添加字符串结束符0，并计算当前参数区参数长度*/
	memcpy(SystemSetting[num].ptr, data, len);
	SystemSetting[num].ptr[len] = 0;
	count = SystemSetting[num].ptr - SystemSettingsBuf + strlen(SystemSetting[num].ptr) + 1;
	/*3.将缓存的参数恢复到参数区*/
	memcpy(SystemSetting[num].ptr + strlen(SystemSetting[num].ptr) + 1, SystemSettingsBufTemp, SETTINGS_BUF_SIZE - count);
	/*4.修改CRC*/
	crc = Modbus_CRC16(SystemSettingsBuf, SETTINGS_BUF_SIZE - 2);
	SystemSettingsBuf[SETTINGS_BUF_SIZE - 1] = (crc >> 8);
	SystemSettingsBuf[SETTINGS_BUF_SIZE - 2] = crc;
	/*5.重新对齐所有参数的指针*/
	System_SettingsAllign();
	
	return System_SettingsSave();
}
/*设置多个参数*/
/*格式-->参数号:参数(字符串) .....*/
uint8_t System_SettingsSetMulti(char* data ,uint16_t num_to_write)
{
	uint32_t pos = 0;
	uint32_t i = 0;
	uint32_t crc = 0;
	uint32_t free_len = 0;
	uint32_t len = 0;
	uint32_t num = 0;
	if(data == NULL)
	{
		mprintf(LOG_ERROR,"param error\r\n");
		return 1;
	}
	if(num_to_write == 0)
	{
		mprintf(LOG_ERROR,"no param need to be set\r\n");
		return 2;
	}


	for(i = 0; i < num_to_write; i++)
	{
		num = data[pos];
		mprintf(LOG_INFO, "num:%d.value:%s.\r\n", num, &data[pos + 1]);
		if(num >= SETTINGS_MAX_NUM)
		{
			mprintf(LOG_ERROR,"param num error:%d.\r\n",data[pos]);
			return SETTINGS_NUM_ERROR;
		}
		/*可用长度 = 该参数原来长度 + 存储总长度 - 已用总长度 - 2个字节crc*/
		free_len = strlen(SystemSetting[num].ptr) + SETTINGS_BUF_SIZE - System_SettingsTotalLength() - 2;
		if(strlen(&data[pos + 1]) > free_len)
		{
			mprintf(LOG_ERROR, "param len error:%d.\r\n",data[pos + 1]);
			return SETTINGS_LEN_ERROR;
		}
		memset(SystemSettingsBufTemp, 0, SETTINGS_BUF_SIZE);
		/*1.先把该参数后面的参数缓存起来*/
		len = SETTINGS_BUF_SIZE - (SystemSetting[num + 1].ptr - SystemSettingsBuf);
		memcpy(SystemSettingsBufTemp, SystemSetting[num + 1].ptr, len);
		/*2.将要写入的参数写入,并计算当前参数区参数长度*/
		strcpy(SystemSetting[num].ptr, &data[pos + 1]);
		len = SystemSetting[num].ptr - SystemSettingsBuf + strlen(SystemSetting[num].ptr) + 1;
		/*3.将缓存的参数恢复到参数区*/
		memcpy(SystemSetting[num].ptr + strlen(SystemSetting[num].ptr) + 1, SystemSettingsBufTemp, SETTINGS_BUF_SIZE - len);
		/*4.重新对齐所有参数的指针*/
		System_SettingsAllign();
		mprintf(LOG_INFO,"set param:%d:%s\r\n",data[pos], &data[pos + 1]);
		pos = 1 + strlen(&data[pos + 1]) + 1;
	}
	/*5.修改CRC*/
	crc = Modbus_CRC16(SystemSettingsBuf, SETTINGS_BUF_SIZE - 2);
	SystemSettingsBuf[SETTINGS_BUF_SIZE - 1] = (crc >> 8);
	SystemSettingsBuf[SETTINGS_BUF_SIZE - 2] = crc;

	return System_SettingsSave();
}

/*****************************test code******************************************/

//typedef enum{
//	SETTINGS_SIGN_STRING = 0,
//	SETTINGS_SOFT_VERSION,
//	SETTINGS_DEVICE_SN,
//	SETTINGS_DEVICE_TYPE,
//	SETTINGS_HARDWARE_VERSION,
//	SETTINGS_SYS_DATETIME,
//	SETTINGS_UART_CONFIG,
//	SETTINGS_AUTO_REBOOT_TIME,
//	SETTINGS_REBOOT,
//	SETTINGS_CONNECT_MODE,
//	SETTINGS_SERVER_IP,
//	SETTINGS_SERVER_PORT,
//	SETTINGS_LAST,				//最后一个参数

//}settings_param;

//void board_settings_default_test(void)
//{

//	memset(SystemSetting, 0, sizeof(SystemSettings) * SETTINGS_MAX_NUM);

//	si.ini_flag = 0;
////	si.start_addr = SETTINGS_START_ADDR;
////	si.stroage_size = SETTINGS_BUF_SIZE;
////	si.storage_read = rf;
////	si.storage_write = wf;
////	si.default_settings = ds;

//	SystemSetting[SETTINGS_SIGN_STRING                  ].name = "SETTINGS_SIGN_STRING------------>:"; SystemSetting[SETTINGS_SIGN_STRING 				].ptr = (uint8_t*)"Author by Cc";				    //效验字符串
//	SystemSetting[SETTINGS_SOFT_VERSION                 ].name = "SETTINGS_SOFT_VERSION----------->:"; SystemSetting[SETTINGS_SOFT_VERSION				].ptr = (uint8_t*)"1.0.0.0";                	    //软件版本
//	SystemSetting[SETTINGS_DEVICE_SN                    ].name = "SETTINGS_DEVICE_SN-------------->:"; SystemSetting[SETTINGS_DEVICE_SN       			].ptr = (uint8_t*)"NB0000000001";           	    //采集器序列号
//	SystemSetting[SETTINGS_DEVICE_TYPE                  ].name = "SETTINGS_DEVICE_TYPE------------>:"; SystemSetting[SETTINGS_DEVICE_TYPE     			].ptr = (uint8_t*)"11";                     	    //设备类型
//	SystemSetting[SETTINGS_HARDWARE_VERSION             ].name = "SETTINGS_HARDWARE_VERSION------->:"; SystemSetting[SETTINGS_HARDWARE_VERSION         	].ptr = (uint8_t*)"1.0";                     	    //硬件版本
//	SystemSetting[SETTINGS_SYS_DATETIME                 ].name = "SETTINGS_SYS_DATETIME----------->:"; SystemSetting[SETTINGS_SYS_DATETIME    			].ptr = (uint8_t*)"2021-04-04 19:58:22";    	    //系统时间
//	SystemSetting[SETTINGS_UART_CONFIG                  ].name = "SETTINGS_UART_CONFIG------------>:"; SystemSetting[SETTINGS_UART_CONFIG    			].ptr = (uint8_t*)"115200,1,0";             	    //串口1通讯波特率，默认115200,停止位 1:0个  2:1.5个 3:2个，效验0:无 1：奇效验 2：偶效验
//	SystemSetting[SETTINGS_AUTO_REBOOT_TIME	            ].name = "SETTINGS_AUTO_REBOOT_TIME------->:"; SystemSetting[SETTINGS_AUTO_REBOOT_TIME			].ptr = (uint8_t*)"1440";                      	    //软件自动重启时间,默认一天重启一次,单位min，0：不重启
//	SystemSetting[SETTINGS_REBOOT			            ].name = "SETTINGS_REBOOT----------------->:"; SystemSetting[SETTINGS_REBOOT					].ptr = (uint8_t*)"1";                      	    //软件重启
//	SystemSetting[SETTINGS_CONNECT_MODE    	    		].name = "SETTINGS_CONNECT_MODE----------->:"; SystemSetting[SETTINGS_CONNECT_MODE    	        ].ptr = (uint8_t*)"1";                      	    //连接服务器模式 0:tcp 1:udp 2:coap 3:onenet
//	SystemSetting[SETTINGS_SERVER_IP                    ].name = "SETTINGS_SERVER_IP-------------->:"; SystemSetting[SETTINGS_SERVER_IP        			].ptr = (uint8_t*)"47.111.81.153";          	    //服务器IP地址 183.56.234.230 "47.111.81.153"
//	SystemSetting[SETTINGS_SERVER_PORT                  ].name = "SETTINGS_SERVER_PORT------------>:"; SystemSetting[SETTINGS_SERVER_PORT      			].ptr = (uint8_t*)"44444";                  	    //服务器端口

//}



